package com.zenithmind.task.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.context.UserContext;
import com.zenithmind.common.exception.BusinessException;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.utils.BeanCopyUtils;
import com.zenithmind.task.mapper.TaskLogMapper;
import com.zenithmind.task.pojo.entity.TaskLog;
import com.zenithmind.task.pojo.query.TaskLogQuery;
import com.zenithmind.task.pojo.vo.TaskLogVO;
import com.zenithmind.task.service.TaskLogService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 任务日志服务实现类
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TaskLogServiceImpl extends ServiceImpl<TaskLogMapper, TaskLog> implements TaskLogService {

    @Override
    public PageResult<TaskLogVO> getTaskLogPage(TaskLogQuery query, String userId) {
        Page<TaskLog> page = new Page<>(query.getCurrent(), query.getSize());
        LambdaQueryWrapper<TaskLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtils.hasText(query.getTaskId()), TaskLog::getTaskId, query.getTaskId())
                .eq(StringUtils.hasText(query.getOperatorId()), TaskLog::getOperatorId, query.getOperatorId())
                .ge(query.getCreateTimeBegin() != null, TaskLog::getCreateTime, query.getCreateTimeBegin())
                .le(query.getCreateTimeEnd() != null, TaskLog::getCreateTime, query.getCreateTimeEnd())
                .orderByDesc(TaskLog::getCreateTime);

        IPage<TaskLog> result = this.page(page, wrapper);
        List<TaskLogVO> voList = result.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());

        return PageResult.of(voList, result.getTotal());
    }

    @Override
    public TaskLogVO getTaskLogById(String id, String userId) {
        TaskLog taskLog = this.getById(id);
        return convertToVO(taskLog);
    }

    @Override
    public Boolean createTaskLog(TaskLog taskLog, String userId) {
        taskLog.setOperatorId(userId);
        taskLog.setOperatorName(UserContext.getUsername());
        return this.save(taskLog);
    }

    @Override
    public Boolean deleteTaskLog(String id, String userId) {
        // In general, logs should not be deleted.
        // Consider changing to logical deletion if needed.
        throw new BusinessException("Logs cannot be deleted.");
    }

    @Override
    public Boolean batchDeleteTaskLogs(List<String> ids, String userId) {
        throw new BusinessException("Logs cannot be deleted in batches.");
    }

    @Override
    public List<TaskLogVO> getTaskLogs(String taskId, String userId) {
        LambdaQueryWrapper<TaskLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TaskLog::getTaskId, taskId).orderByDesc(TaskLog::getCreateTime);
        List<TaskLog> logs = this.list(wrapper);
        return logs.stream().map(this::convertToVO).collect(Collectors.toList());
    }

    @Override
    public Boolean logStatusChange(String taskId, Integer oldStatus, Integer newStatus, String userId, String remark) {
        // Implement the logic for logging status changes.
        return null;
    }

    @Override
    public Boolean logAssignment(String taskId, String assigneeId, String assigneeName, String userId, String remark) {
        // Implement the logic for logging assignments.
        return null;
    }

    @Override
    public Boolean logProgressUpdate(String taskId, Integer oldProgress, Integer newProgress, String userId, String remark) {
        // Implement the logic for logging progress updates.
        return null;
    }

    @Override
    public Boolean logWorkHours(String taskId, Double hours, String description, String userId) {
        // Implement the logic for logging work hours.
        return null;
    }

    @Override
    public PageResult<TaskLogVO> getUserOperationLogs(String userId, Integer pageNum, Integer pageSize) {
        TaskLogQuery query = new TaskLogQuery();
        query.setOperatorId(userId);
        query.setCurrent(pageNum);
        query.setSize(pageSize);
        return getTaskLogPage(query, userId);
    }

    private TaskLogVO convertToVO(TaskLog taskLog) {
        if (taskLog == null) {
            return null;
        }
        return BeanCopyUtils.copyBean(taskLog, TaskLogVO.class);
    }
}
